package server

import (
	"archive/zip"
	"bytes"
	"encoding/base64"
	"errors"
	"gitee.com/gitee-go/server/comm"
	"gitee.com/gitee-go/server/route"
	"gitee.com/gitee-go/utils"
	"gitee.com/gitee-go/utils/httpex"
	"gitee.com/gitee-go/utils/ioex"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"regexp"
	"strings"
)

func regApi() {
	utils.GinRegController(comm.Web, &route.OAuthController{})
	utils.GinRegController(comm.Web, &route.LoginController{})
	utils.GinRegController(comm.Web, &route.SystemController{})

	utils.GinRegController(comm.Web, &route.BadgeController{})
	utils.GinRegController(comm.Web, &route.ReposController{})
	utils.GinRegController(comm.Web, &route.ApiController{})
	utils.GinRegController(comm.Web, &route.RepoController{})
	utils.GinRegController(comm.Web, &route.PipelineController{})
	utils.GinRegController(comm.Web, &route.ManualController{})
	utils.GinRegController(comm.Web, &route.NoticeController{})
	utils.GinRegController(comm.Web, &route.NamespaceController{})
	utils.GinRegController(comm.Web, &route.PluginController{})
}

var rder *zip.Reader

/**
解码前端zip文件
*/
func getRdr() (*zip.Reader, error) {
	if rder != nil {
		return rder, nil
	}
	bts, err := base64.StdEncoding.DecodeString(comm.StaticPkg)
	if err != nil {
		return nil, err
	}
	buf := bytes.NewReader(bts)
	r, err := zip.NewReader(buf, buf.Size())
	if err != nil {
		return nil, err
	}
	rder = r
	return rder, nil
}

/**
获取zip里的文件
*/
func getFile(pth string) (*zip.File, error) {
	if pth == "" {
		return nil, errors.New("param err")
	}
	//println("getFile:" + pth)
	r, err := getRdr()
	if err != nil {
		return nil, err
	}
	for _, f := range r.File {
		//println("f.name:", f.Name)
		if pth == f.Name {
			return f, nil
		}
	}
	return nil, errors.New("file not found")
}

var installBts []byte

/**
如果不是controller的api就按照http path获取打包的前端文件返回给浏览器
1. 通过request path获取前端文件
2. 如果存在就判断是否是index.html,修改其需要安装的标志
3. 如果不是index.html,判断后缀填入header
4. 返回给浏览器
*/
func midUiHandle(c *gin.Context) {
	c.Next()
	if c.Writer.Status() != http.StatusNotFound || c.Writer.Size() > 0 {
		return
	}
	pth := c.Request.RequestURI
	if !strings.HasPrefix(c.Request.RequestURI, "/static/") &&
		!strings.HasPrefix(c.Request.RequestURI, "/favicon.ico") {
		pth = "/index.html"
	}
	r, err := getFile(pth[1:])
	if err != nil {
		//c.String(404, "rdr err:"+err.Error())
		httpex.ResMsgUrl(c, "未找到内容,跳转中...", "/")
		return
	}
	rd, err := r.Open()
	if err != nil {
		//c.String(500, "open err:"+err.Error())
		httpex.ResMsgUrl(c, "内容有误,跳转中...", "/")
		return
	}
	defer rd.Close()
	if pth == "/index.html" {
		if comm.Installed {
			/*if strings.HasPrefix(c.Request.RequestURI, "/install") {
				httpex.ResMsgUrl(c, "正在跳转...", "/")
				return
			}*/
			if installBts == nil {
				bts, err := ioutil.ReadAll(rd)
				if err != nil {
					c.String(500, "open err:"+err.Error())
					return
				}
				rg := regexp.MustCompile(`\<script[\s\w]*\>\W*window\.installed=[\S]+\</script>`)
				installBts = rg.ReplaceAll(bts, []byte(`<script>window.installed=true</script>`))
			}
			c.Writer.Header().Set("Cache-Control", "no-cache")
			c.Writer.Header().Set("Pragma", "no-cache")
			c.Writer.Header().Set("Expires", "0")
			c.Data(200, "text/html", installBts)
			return
		} /*else if c.Request.RequestURI != "/install" {
			httpex.ResMsgUrl(c, "正在跳转到安装...", "/install")
			return
		}*/
	}

	c.Writer.Header().Set("Cache-Control", "max-age=360000000")

	ext := filepath.Ext(r.Name)
	if ext == ".html" {
		c.Writer.Header().Set("Cache-Control", "no-cache")
		c.Writer.Header().Set("Pragma", "no-cache")
		c.Writer.Header().Set("Expires", "0")
		c.Writer.Header().Set("Content-Type", "text/html")
	} else if ext == ".css" {
		c.Writer.Header().Set("Content-Type", "text/css")
	} else if ext == ".js" {
		c.Writer.Header().Set("Content-Type", "application/javascript")
	} else if ext == ".svg" {
		c.Writer.Header().Set("Content-Type", "image/svg+xml")
	}
	c.Status(200)
	bts := make([]byte, 1024)
	for !ioex.CheckContext(c) {
		n, err := rd.Read(bts)
		if n > 0 {
			c.Writer.Write(bts[:n])
		}
		if err != nil {
			break
		}
	}
	//c.String(200,"path:"+c.Request.RequestURI)
}
